package com.tecklab.demo.easyrules;

import com.tecklab.demo.utils.LogConsolehUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * 监视规则文件（YAML格式）的变化。
 * 当规则文件发生变化时，记录日志信息。
 */
@Slf4j
public class YamlRuleChangeWatcher {

    /**
     * 程序入口点。
     * 初始化日志级别，并开始监视规则文件的变化。
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        LogConsolehUtils.setInfoLevel();
        YamlRuleChangeWatcher.startMonitorFileChange("classpath:rules/rules.yml");
    }

    /**
     * 开始监视指定路径的文件变化。
     * 使用Apache Commons IO库来实现文件变化的监听。
     * @param targetFilePath 要监视的文件的路径
     * @throws IOException 如果文件操作发生错误
     * @throws InterruptedException 如果线程操作被中断
     */
    public static void startMonitorFileChange(String targetFilePath) {
        File targetFile = null;
        try {
            targetFile = ResourceUtils.getFile(targetFilePath);
            String fullPath = targetFile.getPath();
            log.info("目标文件的全路径是: {}", fullPath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        // 获取目标文件的父目录，用于设置文件观察者
        File parentDirectory = targetFile.getParentFile();

        // 创建一个文件过滤器，只监视特定名称的文件（即目标规则文件）
        NameFileFilter targetFileFilter = new NameFileFilter(targetFile.getName());
        // 创建文件观察者，指定父目录和文件过滤器
        FileAlterationObserver observer = new FileAlterationObserver(parentDirectory, targetFileFilter);

        // 创建文件变化监听器，当文件变化时记录日志
        // 创建一个文件监听器
        FileAlterationListener listener = new FileAlterationListenerAdaptor() {
            @Override
            public void onFileChange(File file) {
                log.info("File {} has been modified!", file.getName());
            }
        };

        // 将监听器添加到观察者
        // 将监听器添加到观察者
        observer.addListener(listener);

        // 创建文件监控器，设置监控间隔时间为5秒
        // 创建并启动文件监控器
        FileAlterationMonitor monitor = new FileAlterationMonitor(5000);
        // 将观察者添加到监控器
        monitor.addObserver(observer);
        try {
            monitor.start(); // 启动监控
        } catch (Exception e) {
            try {
                monitor.stop(); // 在异常发生时，确保资源被释放
            } catch (Exception ex) {
                throw new RuntimeException("file monitor启动失败之后，关闭出现异常", e);
            }
            throw new RuntimeException("FileAlterationMonitor启动失败", e);
        }
    }
}
